오늘 풀어본 문제는 백준의 10830번 문제1이다. 문제 풀이에 사용한 언어는 C++ 이다.
이 문제의 내용과 조건은 다음과 같다.
크기가 $N*N$ 인 행렬 $A$ 가 주어진다. 이때, $A$ 의 $B$ 제곱을 구하는 프로그램을 작성하시오. 수가 매우 커질 수 있으니, $A^B$ 의 각 원소를 $1,000$ 으로 나눈 나머지를 출력한다.
첫째 줄에 행렬의 크기 $N$ 과 $B$ 가 주어진다. $(2 \leq N \leq 5,\ 1 \leq B \leq 100,000,000,000)$
둘째 줄부터 $N$ 개의 줄에 행렬의 각 원소가 주어진다. 행렬의 각 원소는 $1,000$ 보다 작거나 같은 자연수 또는 $0$ 이다.
첫째 줄부터 $N$ 개의 줄에 걸쳐 행렬 $A$ 를 $B$ 제곱한 결과를 출력한다.
문제를 보고 분할 정복을 이용한 거듭제곱 문제임을 알 수 있었다. 단, 여기서는 행렬을 이용해야 했기 때문에 직접 Matrix
클래스를 구현하여 사용하였다.
코드는 다음과 같이 작성하였다.
#include <bits/stdc++.h>
template <typename T>
class Matrix {
public:
size_t row;
size_t column;
T** elements;
public:
Matrix(size_t row, size_t column) : row(row), column(column) {
elements = new T * [row];
for (size_t i = 0; i < row; i++) {
elements[i] = new T[column]{};
}
}
Matrix(size_t size, bool isIdentity = false) : row(size), column(size) {
elements = new T * [size];
for (size_t i = 0; i < size; i++) {
elements[i] = new T[size]{};
if (isIdentity == true) {
elements[i][i] = static_cast<T>(1);
}
}
}
Matrix(const Matrix& other) : row(other.row), column(other.column) {
elements = new T * [row];
for (size_t i = 0; i < row; i++) {
elements[i] = new T[column];
for (size_t j = 0; j < column; j++) {
elements[i][j] = other.elements[i][j];
}
}
}
~Matrix() {
for (size_t i = 0; i < row; i++) {
delete[] elements[i];
}
delete[] elements;
}
T* operator[] (size_t idx) {
return elements[idx];
}
Matrix& operator= (const Matrix& other) {
if (this == &other) {
return *this;
}
for (size_t i = 0; i < row; i++) {
delete[] elements[i];
}
delete[] elements;
row = other.row;
column = other.column;
elements = new T * [row];
for (size_t i = 0; i < row; i++) {
elements[i] = new T[column];
for (size_t j = 0; j < column; j++) {
elements[i][j] = other.elements[i][j];
}
}
return *this;
}
Matrix operator* (const Matrix& other) {
Matrix result(this->row, other.column);
for (size_t i = 0; i < result.row; i++) {
for (size_t j = 0; j < result.column; j++) {
result.elements[i][j] = 0;
for (size_t k = 0; k < this->column; k++) {
result.elements[i][j] += (this->elements[i][k] * other.elements[k][j] % static_cast<T>(1000));
result.elements[i][j] %= static_cast<T>(1000);
}
}
}
return result;
}
Matrix power(size_t exponent) {
Matrix base(*this);
Matrix result(row, true);
while (exponent > 0) {
if (exponent % 2 == 1) {
result = result * base;
}
exponent = exponent / 2;
base = base * base;
}
return result;
}
};
using namespace std;
int main(void) {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
long long A, B;
cin >> A >> B;
Matrix<long long> mat(A);
for (long long i = 0; i < A; i++) {
for (long long j = 0; j < A; j++) {
cin >> mat[i][j];
}
}
Matrix<long long> result(mat.power(B));
for (size_t i = 0; i < mat.row; i++) {
for (size_t j = 0; j < mat.column; j++) {
cout << result.elements[i][j] << " ";
}
cout << "\n";
}
return 0;
}
그러자 모든 테스트 케이스를 통과하고 정답이 나오는 것을 확인할 수 있었다.
PS를 하다보면 이런 식으로 직접 자료구조나 클래스를 구현하는 문제들이 뭔가 재밌다고 느껴진다. 객체 수업과 데이터구조 시간에 배운 내용을 써먹는다는 느낌이어서 그런 것일까?
그치만 매일 이런 문제가 나오면 너무 힘들 것 같다. 한 달에 한두 개 정도만 나오면 딱 적당할 것 같다.
오늘 만들어둔 Matrix
클래스는 살짝 수정하여 내 레포지토리2에 저장해두었으니 필요한 사람은 참고하길 바란다.
오늘의 PS는 여기까지!
1: https://www.acmicpc.net/problem/10830
2: https://github.com/ChoiCube84/baekjoon-solutions/blob/main/C%2B%2B/custom_data_structures/matrix.hpp